package com.golaberto.client;

import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.Timer;
import com.google.gwt.user.client.ui.HTMLTable;
import com.google.gwt.user.client.ui.HTMLTable.CellFormatter;
import com.google.gwt.user.client.ui.HTMLTable.RowFormatter;
import com.google.gwt.user.client.ui.Grid;
import com.google.gwt.user.client.ui.TextBox;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.DockPanel;
import com.google.gwt.user.client.ui.HorizontalPanel;
import com.google.gwt.user.client.ui.VerticalPanel;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.SourcesTableEvents;
import com.google.gwt.user.client.ui.TableListener;
import com.google.gwt.user.client.ui.KeyboardListener;
import com.google.gwt.user.client.ui.ClickListener;
import com.google.gwt.user.client.ui.Widget;

public class FilteredGrid extends Composite
    implements KeyboardListener, ClickListener, TableListener {

  public interface ListItemsCallback {
    public void getItems(String text, int page, int count);
  }

  private class FilteredGridTimer extends Timer {
    private FilteredGrid parent_;

    public FilteredGridTimer(FilteredGrid parent) {
      super();
      parent_ = parent;
    }

    public void run() {
      parent_.updateGrid();
    }
  }
   
  private ListItemsCallback callback_ = null;
  private FilteredGridTimer timer_ = new FilteredGridTimer(this);
  private Grid grid_ = null;
  private TextBox tb_ = new TextBox();
  private Button next_ = new Button(">");
  private Button prev_ = new Button("<");
  private int current_page_ = 0;
  private int rows_;
  private int columns_;
  private int current_row_ = -1;
  private int last_active_ = 1;
  private String current_text_ = new String();

  public FilteredGrid(int rows, int columns, boolean has_header) {
    rows_ = rows + 1;
    columns_ = columns;

    grid_ = new Grid(rows_, columns_);
    grid_.setBorderWidth(1);
    grid_.setWidth("100%");
    grid_.addTableListener(this);

    HTMLTable.RowFormatter row_f = grid_.getRowFormatter();
    HTMLTable.CellFormatter cell_f = grid_.getCellFormatter();
    for (int i = 0; i < rows_; ++i) {
      for (int j = 0; j < columns_; ++j) {
        cell_f.setHeight(i, j, "25px");
        Label label = new Label();
        label.setWordWrap(true);
        grid_.setWidget(i, j, label);
      }
      row_f.setStyleName(i, "FilteredGrid-disabled");
    }

    row_f.setVisible(0, has_header);
    row_f.setStyleName(0, "FilteredGrid-header");

    tb_.addKeyboardListener(this);
    prev_.addClickListener(this);
    next_.addClickListener(this);

    final HorizontalPanel top = new HorizontalPanel();
    top.add(tb_);
    top.add(prev_);
    top.add(next_);
    top.setWidth("100%");

    final DockPanel main = new DockPanel();
    main.add(top, DockPanel.NORTH);
    main.add(grid_, DockPanel.CENTER);

    initWidget(main);
    updateGrid();
  }

  public void onCellClicked(SourcesTableEvents sender, int row, int cell) {
    HTMLTable.RowFormatter row_f = grid_.getRowFormatter();
    if (row > 0 && row < last_active_) {
      if (current_row_ != -1) {
        row_f.setStyleName(current_row_, "FilteredGrid-normal");
      }
      row_f.setStyleName(row, "FilteredGrid-selected");
      current_row_ = row;
    }
  }

  public void setHeader(int i, String text) {
    setCellText(0, i, text);
  }

  public void setListItemsCallback(ListItemsCallback cb) {
    callback_ = cb;
  }

  public void onClick(Widget sender) {
    if (sender == prev_) {
      --current_page_;
    } else if (sender == next_) {
      ++current_page_;
    }

    updateGrid();
  }

  public void onKeyPress(Widget sender, char keyCode, int modifiers) {
  }
  public void onKeyDown(Widget sender, char keyCode, int modifiers) {
  }

  /**
   * A key was released
   */
  public void onKeyUp(Widget sender, char keyCode, int modifiers) {
    if(keyCode == KEY_ESCAPE)
    {
      tb_.setText("");
    }

    timer_.cancel();
    timer_.schedule(1000);
  }

  private void setCellText(int i, int j, String text) {
    Label label = (Label)grid_.getWidget(i, j);
    label.setText(text);
  }

  private void clear() {
    HTMLTable.RowFormatter row_f = grid_.getRowFormatter();
    for (int i = 1; i < rows_; ++i) {
      for (int j = 0; j < columns_; ++j) {
        setCellText(i, j, "");
      }
      row_f.setStyleName(i, "FilteredGrid-disabled");
    }
    last_active_ = 1;
    current_row_ = -1;
  }

  public void updateGrid() {
    String text = tb_.getText();
    if (!current_text_.equals(text)) {
      current_text_ = text;
      current_page_ = 0;
    }
    clear();
    setCellText(1, 0, "Fetching...");

    if (callback_ != null) {
      callback_.getItems(current_text_, current_page_, rows_);
    } else {
      onGetItemsDone(new String[][]{});
    }
  }

  public void onGetItemsDone(String[][] items) {
    clear();
    HTMLTable.RowFormatter row_f = grid_.getRowFormatter();
    for (int i = 0; i < items.length; ++i) {
      for (int j = 0; j < items[i].length; ++j) {
        setCellText(i+1, j, items[i][j]);
      }
      row_f.setStyleName(i+1, "FilteredGrid-normal");
      last_active_ = i+2;
    }

    prev_.setEnabled(current_page_ != 0);
    next_.setEnabled(items.length >= rows_ - 1);
  }
}
